iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
Software Development

從 Vibe Coding 到可維護專案:用 Hermes Agent 重讀 RoomRush Android 專題系列 第 11 篇

Day 11 | 一間教室的一週課表,在資料庫裡長什麼樣子?

  • 分享至 

  • xImage
  •  

前言:RoomRush 的核心資料模型如何表示一間教室的一週課表?

結束了空教室查詢系統的第一階段-「使用者查詢流程」之後,我們第二階段要了解的是 RoomRush 的「資料來源主線」。

首先我們要讀的檔案是- ClassroomSchedule.kt ,這對於我們理解一間教室的一週課表如何表示成 Room Entity 與資料表欄位的部分扮演著很重要的角色。


一開始我認為

剛開始寫資料庫時,我們組內討論是將我們的教室課表寫成 CSV 檔案,之後再做進一步的處理。原本我們以為這樣的寫法,對於剛學習 Android 的我們會很困難;然而,更困難的部份反而是:我們還需要把 CSV 資料表的內容,轉換成 Kotlin 裡面的語法,讓程式可以看得懂。

一開始看到 ClassroomSchedule.kt 時,我把它理解成「將 CSV 轉換成 ClassroomSchedule,可能就像是轉換成 Kotlin 的語法來讀取」。但實際了解後才發現,它是 把 CSV 的欄位值解析成 Kotlin 物件,之後存進 Room Database。


資料庫長什麼樣子?

classroom,Mon_1,Mon_2,Mon_3,...,Fri_8,ClassroomType
SF131,X,X,X,...,O,Normal
SF204,O,O,O,...,X,Normal
SF337,O,O,X,...,O,Computer

這就是 RoomRush 原始課表資料的一部分。每一列代表一間教室,而 Mon_1、Mon_2 到 Fri_8 分別代表星期一到星期五的各個節次。


實際讀完後,ClassroomSchedule.kt負責什麼

和 Hermes Agent 一起重讀檔案後,我了解 ClassroomSchedule.kt 是 RoomRush 的課表資料模型,也是 Room Database 的 Entity。

簡單來說,它是 CSV 原始資料與 Kotlin 程式碼之間的橋樑,負責將課表 CSV 的欄位映射成 Kotlin 的屬性,並直接對應到 Room Database 裡的 classroom_schedules 資料表。

仔細剖析程式碼,這份 Entity 主要由以下四個關鍵部分組成:

這份 Entity 主要由以下四個關鍵部分組成:

1. Entity 對應資料表

@Entity(tableName = "classroom_schedules")
data class ClassroomSchedule(...)
  • 技術細節:這表示 ClassroomSchedule 會對應到 Room Database 裡的 classroom_schedules 資料表;@Entity 就是在告訴 Room:這個 class 對應一張資料表。

2. 設定 Primary Key(主鍵)

@PrimaryKey
val classroom: String
  • 技術細節:主鍵需要能唯一識別一筆資料。而classroom 是 教室名稱 。例如 SF130、ES301,因為每間教室在資料表裡應該只出現一次,所以可以當主鍵。

3. ColumnInfo 對應欄位名稱

@ColumnInfo(name = "Mon_1") val mon1: String?
@ColumnInfo(name = "Tue_N") val tueN: String?
@ColumnInfo(name = "Fri_8") val fri8: String?
  • 技術細節:資料表與原始 CSV 中的欄位命名採用底線分隔(如 Mon_1),但 Kotlin 程式碼習慣使用 Camel Case(如 mon1)讀取。而 @ColumnInfo 負責 對應資料庫欄位名稱和 Kotlin 屬性名稱 。

補充: mon1 表示星期一第一節, tueN 表示星期二中午, fri8 表示星期五第八節,都是對應到資料表裡面的欄位。

4. classroomType 擴充欄位

@ColumnInfo(name = "ClassroomType") val classroomType: String?
  • 技術細節:classroomType 代表教室類型,例如 Normal、Computer 等。這正是前幾天在詳細頁(RoomDetailActivity )中,被我們拿來轉譯成對應的中文(如「一般教室」、「電腦教室」),並判斷是否可飲食。

它接在哪一條流程上

CSV 原始資料
    ↓
讀取一列教室課表
    ↓
建立 ClassroomSchedule(Room Entity)
    ↓
寫入 Room Database
    ↓
Repository / DAO 取得課表資料
    ↓
QueryResultViewModel
    ↓
根據星期+節次找到對應欄位
    ↓
判斷該時段是否為 X
    ↓
篩選出可用教室

Hermes Agent 幫我檢查出的重點

ClassroomSchedule 是 RoomRush 的 Room Entity,對應到 Room Database 裡的 classroom_schedules 資料表。

每一筆 ClassroomSchedule 代表一間教室的一週課表。

  • classroom 是主鍵,用來唯一識別教室。
  • Mon_1、Tue_N、Fri_8 等 CSV / 資料表欄位,透過 @ColumnInfo 對應到 Kotlin 屬性 mon1、tueN、fri8。
  • 在查詢邏輯中,X 代表該時段被佔用,而不是 X 的欄位會被視為可用。classroomType 則代表教室類型,會在詳細頁轉成中文並用來判斷是否可飲食。

這個檔案帶出的維護觀察

「一間教室一列、每個節次一個欄位(如 mon1 到 fri8)」 這種橫向展開的資料設計,對「看一間教室整週課表」很直覺。但在後續維護上卻帶來明顯的硬傷:

  1. 欄位很多:一週五天搭配各節次,單一 Entity 就塞進了超過 45 個欄位,資料結構過於冗長。
  2. 擴充性較差:未來如果想支援「週六授課」或「夜間部時段」,就必須更動資料表結構(Schema),還得重寫 Room Migration。
  3. 程式牽一髮動全身:若要增加時段欄位,從 Entity、DAO 到程式裡用反射(Reflection)拼湊欄位名稱的邏輯,全部都得重新修改對齊。
  4. 無法支援時間維度:只能呈現單一固定排程,無法彈性擴充「單雙週」、「學期切換」或「臨時借用」等情境。

未來如果想重構程式,可拆為「教室表」與一對多的「時段表記錄」,或將資料轉為縱向儲存,新增時段只需增加資料筆數,完全不需變動資料表結構。


小結

進入資料來源主線後,我第一個看的檔案是 ClassroomSchedule.kt。

這個檔案不像 Activity 那樣控制畫面,而是定義 RoomRush 的課表資料長什麼樣子。每一筆資料代表一間教室,欄位則代表星期一到星期五各節次的使用狀態。

這種設計的好處是直覺:打開一筆教室資料,就能看到它整週每個時段是否被使用。但它也有明顯限制,因為每個時段都被設計成固定欄位。如果未來要增加更多節次、星期六或更複雜的課表規則,就可能需要修改資料表和查詢邏輯。

這讓我開始理解,資料模型不只是「存資料」,也會影響後續功能的彈性與維護成本。

用一句話總結這檔案,我會說:

ClassroomSchedule 是 RoomRush 的課表資料模型;一筆資料代表一間教室的一週課表,每個欄位代表某天某節是否可用。


下一篇預告:App 要查資料、改資料,Room DAO 負責哪一層?

了解 ClassroomSchedule.kt 是如何定義 RoomRush 的課表資料長什麼樣子後。下一個關鍵問題隨之而來:App 到底要怎麼對這張資料表進行讀寫?

作為資料庫與 Kotlin 程式碼之間的「門衛兼翻譯官」,DAO (Data Access Object) 負責定義所有對 classroom_schedules 資料表的操作方法,例如查詢、新增、更新與刪除。

下一篇,我們將拆解 RoomRush 中的 DAO 設計- ClassroomScheduleDao.kt 。


上一篇
Day 10 | 從首頁到詳細頁:我把使用者查空教室流程串起來了
下一篇
Day 12 | App 要查資料、改資料,Room DAO 負責哪一層?
系列文
從 Vibe Coding 到可維護專案:用 Hermes Agent 重讀 RoomRush Android 專題 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言